//0629
/*\u9700\u8981\u4f8b\u5316256*32\u7684RAM*/

/*
\u63a5\u53e3\u5206\u7c7b\uff1a
    1.\u6570\u636e\u5305\u901a\u8def\uff1a
        node_addr:\u8282\u70b9\u5730\u5740
        node_look_fail:\u67e5\u627e\u5931\u8d25
        node_out_port_num:\uff08\u6ce8\u610f\uff09\u4e0d\u4e3a2'b01\u65f6\u4e00\u5b9a\u5bfc\u81f4result\u8f93\u51fa1\uff08\u8868\u793a\u4e0d\u9700\u8981\u6d41\u63a7\uff09
                                   \u4e3a2'b01\u65f6\u624d\u4f1a\u7f13\u5b58addr\uff08\u540c\u65f6addr_reg\u5730\u5740\u624d\u4f1a\u7ed9\u5230addr_ram\uff09\uff1b\u540c\u65f6\u4e5f\u4f1a\u4ea7\u751frw_en\u4fe1\u53f7\u3002
        frame_length:\u5e27\u957f\u4fe1\u606f
        result:\u6d41\u63a7\u7ed3\u679c

    \u3010CPU\u901a\u8def\u6307\u7684\u662fHINOC\u5de5\u7a0b\u7684CPU\u63a5\u53e3\u7684\u5bc4\u5b58\u5668\u3011
    2.CPU\u901a\u8def\uff1a\uff08\u53d7\u5230flowctrl_daram_addr[11]\u7684\u5f71\u54cd\uff0cflowctrl_daram_addr\u662f\u4e00\u4e2a\u5bc4\u5b58\u5668\uff09
        flowctrl_daram_addr[11] == 1'b1\u65f6\u8868\u793a\u8bbf\u95ee\u7684\u662fclass_flow
        flowctrl_daram_addr[11] == 1'b0\u65f6\u8868\u793a\u8bbf\u95ee\u7684\u662fnode_flow
        flowctrl_daram_addr[9:0]\u8868\u793a\u8bbf\u95ee\u54ea\u4e2a\u5730\u5740

    \u8ffd\u8e2aflowctrl_daram_addr\u7ed3\u679c\uff1a\u5728\u201ccpu_rw_dpram_unit.v\u201d\u6587\u4ef6\u91cc\u9762\u5f53"sel_en"\u4fe1\u53f7\u4e3a1'b1\u65f6\u9009\u62e9cpu_addr_in\uff08Himac_top\u5916\u90e8\u8f93\u5165\u7684\u4fe1\u53f7\uff09
    \u800c\u5f53cpu_addr_in[`REG_ADDR_WIDTH-1 : `REG_ADDR_WIDTH-`RAM_CS_WIDTH] == `ADDR_RAM_FLOWCTRL\u65f6sel_en==1'b1
    
    \u603b\u7ed3\uff1a\u4e5f\u5c31\u662f\u8bf4\u5f53\u66f4\u9876\u5c42\u7684cpu_addr_in\u67d0\u4e9b\u4f4d\u4e3a`ADDR_RAM_FLOWCTRL\u65f6\u8868\u793a\u9700\u8981\u5bf9\u6d41\u63a7\u8fdb\u884c\u64cd\u4f5c------\u90a3\u4e48\u8fd9\u4e9b\u4f4d\u5177\u4f53\u662f\u591a\u5c11\uff0c\u9700\u8981\u53c2\u8003\u8fd9\u4e9b\u5b8f\u5b9a\u4e49
*/
`include "top_define.v"
module flow_ctrl_top_top  (
			clk                          ,
            rst_n                        ,
            clk_cpu                      ,
            rst_n_cpu                    ,
            ram_dp_cfg_register          ,
            //\u548c\u63a5\u6536\u8c03\u5ea6\u76f8\u5173
			node_addr                    , //flow_ctrl_node\u7684addr
			node_addr_en                 , //flow_ctrl_node\u7684addr_en
			node_look_fail               , //flow_ctrl_node\u7684look_fail
			node_out_port_num            , //flow_ctrl_node\u7684out_port_num
			frame_length_en              , //\u5e27\u957f\u5ea6\u4fe1\u606f\u6709\u6548
			frame_length                 , //\u4e24\u4e2a\u6a21\u5757\u7684\u5e27\u957f\u5ea6
            do_not_flow_ctrl             ,
            //\u548c\u63a5\u6536\u8c03\u5ea6\u76f8\u5173\uff08\u6d41\u5206\u7c7b\u6d41\u63a7\uff09 
			class_flow_ctrl_en           , //flow_ctrl_classifier\u7684\u201c\u5730\u5740\u6709\u6548\u201d\u548c\u201c\u5e27\u6709\u6548\u4e4b\u4e00\u201d
			class_flow_ctrl_num          , //flow_ctrl_classifier\u7684\u201c\u5730\u5740\u201d
            
            //\u7531\u5185\u90e8\u9009\u901a\u7ed9node_flow_ctrl\u6216\u662fclass_flow_ctrl
            np_data_out                  ,
            np_data_in                   ,
            np_addr_in                   ,
            np_addr_ctrl                 ,                     
            np_rd_vld                    , //\u8bfb\u51fa\u6570\u636e\u6709\u6548
            //\u548c\u63a5\u6536\u8c03\u5ea6\u76f8\u5173
            result                       , //\u4e24\u4e2a\u6a21\u5757\u7684\u8f93\u51fa\u8ba1\u7b97\u5f97\u5230\u8f93\u51fa
            result_en                      //\u8f93\u51fa\u4fe1\u606f\u6709\u6548
);                  

(*mark_debug = "true"*)input        clk                        ;
(*mark_debug = "true"*)input        rst_n                      ;
(*mark_debug = "true"*)input        clk_cpu                    ;
(*mark_debug = "true"*)input        rst_n_cpu                  ;
                       input[11:0]  ram_dp_cfg_register        ;
(*mark_debug = "true"*)input[7 :0]  node_addr                  ;
(*mark_debug = "true"*)input        node_addr_en               ;
(*mark_debug = "true"*)input        node_look_fail             ;
(*mark_debug = "true"*)input[1:0]   node_out_port_num          ;
(*mark_debug = "true"*)input        frame_length_en            ;
(*mark_debug = "true"*)input[10:0]  frame_length               ;
(*mark_debug = "true"*)input        class_flow_ctrl_en         ;
(*mark_debug = "true"*)input[6:0]   class_flow_ctrl_num        ;
(*mark_debug = "true"*)input        do_not_flow_ctrl           ; 

(*mark_debug = "true"*)output reg  [31:0]  np_data_out;
(*mark_debug = "true"*)input  wire [31:0]  np_data_in;
(*mark_debug = "true"*)input  wire [16:0]  np_addr_in;
(*mark_debug = "true"*)input  wire [ 1:0]  np_addr_ctrl;
(*mark_debug = "true"*)output reg          np_rd_vld;

(*mark_debug = "true"*) output   reg     result                    ;
(*mark_debug = "true"*) output   reg     result_en                 ;

(*mark_debug = "true"*) wire result_en_node;
(*mark_debug = "true"*) wire result_en_class;
(*mark_debug = "true"*) wire result_node;
(*mark_debug = "true"*) wire result_class;

wire [31:0]  node_cpu_fdata_out        ;
reg  [9:0]   node_cpu_faddr             ;
reg  [31:0]  node_cpu_fdata_in          ;
wire         node_cpu_fread_write       ;
reg          node_cpu_wren;
reg          node_cpu_rden;


wire [31:0]  classflow_cpu_fdata_out  ;
reg  [9:0]   classflow_cpu_faddr        ;
reg  [31:0]  classflow_cpu_fdata_in    ;
wire         classflow_cpu_fread_write  ;
reg          classflow_cpu_wren;
reg          classflow_cpu_rden;


// wire [6:0]reg_addr_in;
// wire [31:0]reg_data_in;
// wire reg_wren_in;
// wire reg_rden_in;
// reg [11:0]ram_dp_cfg_register;
reg node_cpu_rden_d1, node_cpu_rden_d2;
reg classflow_cpu_rden_d1, classflow_cpu_rden_d2;

// reg reg_rden_in_d1;
// reg [6:0]reg_addr_in_d1;
// reg [31:0]np_addr_in_d1;

always@( * ) begin
    // if(!rst_n)
    // 	begin
    // 		result<=1'b1;
    // 		result_en<=1'b0;
    // 	end
    // else 
    if(result_en_node && result_en_class)
    	begin
    		result      =result_node || result_class;
    		result_en   =1'b1;
    	end
    else if(result_en_node)
    	begin
    		result      =result_node ;
    		result_en   =1'b1;
    	end
    else
    	begin
    		result      =1'b1;
    		result_en   =1'b0;
    	end
end

flow_ctrl_top flow_ctrl_node (
    .clk(clk)            		                                ,
    .rst_n(rst_n)             		                            ,
    .addr(node_addr)                                            ,
    .addr_en(node_addr_en)                                      ,
    .look_fail(node_look_fail)                                  ,
    .do_not_flow_ctrl(do_not_flow_ctrl)                         ,
    .ram_dp_cfg_register(ram_dp_cfg_register)				    ,
    .out_port_num(node_out_port_num)                            , 
    .frame_length_en(frame_length_en)                           ,
    .frame_length(frame_length)                                 ,
    .clk_cpu(clk_cpu)                                           ,
    .rst_n_cpu(rst_n_cpu)                                       ,
    .cpu_fdata_out(node_cpu_fdata_out)                          ,
    .cpu_faddr(node_cpu_faddr)                                  ,
    .cpu_fdata_in(node_cpu_fdata_in)                            ,
    .cpu_fread_write(node_cpu_fread_write)                      ,
    					
    .result(result_node)                                        , //\u7528\u4ee5\u8ba1\u7b97\u8f93\u51fa
    .result_en(result_en_node)                                  , //\u7528\u4ee5\u9009\u901a
    .des_node_id()        
);

flow_ctrl_top flow_ctrl_classifier (
  .clk(clk)            		                                    ,
  .rst_n(rst_n)             		                            ,
  .addr({1'b0,class_flow_ctrl_num})                             ,
  .addr_en(class_flow_ctrl_en)                                  ,
  .look_fail(1'b0)                                              ,
  .do_not_flow_ctrl(do_not_flow_ctrl)                           ,
  .ram_dp_cfg_register(ram_dp_cfg_register)				        ,					
  .out_port_num(2'b01)                                          , 
  .frame_length_en(frame_length_en &&class_flow_ctrl_en)        ,       
  .frame_length(frame_length)                                   ,
  .clk_cpu(clk_cpu)                                             ,
  .rst_n_cpu(rst_n_cpu)                                         ,
  .cpu_fdata_out(classflow_cpu_fdata_out)                       ,
  .cpu_faddr(classflow_cpu_faddr)                               ,
  .cpu_fdata_in(classflow_cpu_fdata_in)                         ,
  .cpu_fread_write(classflow_cpu_fread_write)                   ,
  					
  .result(result_class)                                         , //\u7528\u4ee5\u8ba1\u7b97\u8f93\u51fa
  .result_en(result_en_class)                                   , //\u7528\u4ee5\u9009\u901a
  .des_node_id()        
);
// assign reg_addr_in = np_addr_in[6:0];
// assign reg_data_in = np_data_in;
// assign reg_wren_in = np_addr_ctrl[5];
// assign reg_rden_in = np_addr_ctrl[4];
//===============================================================
//node
always @(posedge clk or negedge rst_n) begin
    if(~rst_n)begin
        node_cpu_wren <= 1'b0;
        node_cpu_fdata_in <= 32'b0;
    end else if (np_addr_ctrl[1] && np_addr_in[16:10]>=`TOKEN_RATE_BASE_ADDR && np_addr_in[16:10]<`FRAME_LEN_CNT_BASE_ADDR)begin
        node_cpu_wren <= 1'b1;
        node_cpu_fdata_in <= np_data_in;
    end else begin
        node_cpu_wren <= 1'b0;
    end
end

always @(posedge clk or negedge rst_n) begin
    if(~rst_n)
        node_cpu_faddr <= 10'b0;
    else if ((|np_addr_ctrl[1:0]) && np_addr_in[16:10]>=`TOKEN_RATE_BASE_ADDR && np_addr_in[16:10]<`FRAME_LEN_CNT_BASE_ADDR)
        node_cpu_faddr <= np_addr_in[9:0];
end

always @(posedge clk or negedge rst_n) begin
    if(~rst_n)
        node_cpu_rden <= 1'b0;
    else if (np_addr_ctrl[0] && np_addr_in[16:10]>=`TOKEN_RATE_BASE_ADDR && np_addr_in[16:10]<`FRAME_LEN_CNT_BASE_ADDR)
        node_cpu_rden <= 1'b1;
    else
        node_cpu_rden <= 1'b0;
end

assign node_cpu_fread_write = node_cpu_wren;
//-----------------------------------------------------------
//classflow
always @(posedge clk or negedge rst_n) begin
    if(~rst_n)begin
        classflow_cpu_wren <= 1'b0;
        classflow_cpu_fdata_in <= 32'b0;
    end else if (np_addr_ctrl[1] && np_addr_in[16:10]>=`FRAME_LEN_CNT_BASE_ADDR && np_addr_in[16:10]<`FIELD_SEL_BASE_ADDR)begin
        classflow_cpu_wren <= 1'b1;
        classflow_cpu_fdata_in <= np_data_in;
    end else begin
        classflow_cpu_wren <= 1'b0;
    end
end

always @(posedge clk or negedge rst_n) begin
    if(~rst_n)
        classflow_cpu_faddr <= 10'b0;
    else if ((|np_addr_ctrl[1:0]) && np_addr_in[16:10]>=`FRAME_LEN_CNT_BASE_ADDR && np_addr_in[16:10]<`FIELD_SEL_BASE_ADDR)
        classflow_cpu_faddr <= np_addr_in[9:0];
end

always @(posedge clk or negedge rst_n) begin
    if(~rst_n)
        classflow_cpu_rden <= 1'b0;
    else if (np_addr_ctrl[0] && np_addr_in[16:10]>=`FRAME_LEN_CNT_BASE_ADDR && np_addr_in[16:10]<`FIELD_SEL_BASE_ADDR)
        classflow_cpu_rden <= 1'b1;
    else
        classflow_cpu_rden <= 1'b0;
end

assign classflow_cpu_fread_write = classflow_cpu_wren;
//==================================================================
// always @(posedge clk or negedge rst_n) begin
//     if(~rst_n)
//         ram_dp_cfg_register <= 12'h69a;
//     else if(reg_wren_in&&(reg_addr_in==`ADDR_RAM_DP_CFG_REGISTER))
//         ram_dp_cfg_register <= reg_data_in;
//     else
//         ram_dp_cfg_register <= ram_dp_cfg_register;
// end

always@(posedge clk or negedge rst_n)begin
    if(~rst_n)begin
        node_cpu_rden_d1 <= 1'b0;
        classflow_cpu_rden_d1 <= 1'b0;
        //reg_rden_in_d1 <= 1'b0;
        //reg_addr_in_d1 <= 7'b0;
    end else begin
        node_cpu_rden_d1 <= node_cpu_rden;
        classflow_cpu_rden_d1 <= classflow_cpu_rden;
        //reg_rden_in_d1 <= reg_rden_in;
        //reg_addr_in_d1 <= reg_addr_in;
    end
end
always@(posedge clk or negedge rst_n)begin
    if(~rst_n)begin
        node_cpu_rden_d2 <= 1'b0;
        classflow_cpu_rden_d2 <= 1'b0;
    end else begin
        node_cpu_rden_d2 <= node_cpu_rden_d1;
        classflow_cpu_rden_d2 <= classflow_cpu_rden_d1;
    end
end
    //\u5ef6\u65f6\u4e00\u62cd
reg[31:0] node_cpu_fdata_out_d1, classflow_cpu_fdata_out_d1 ;
always@(posedge clk or negedge rst_n)begin
    if(~rst_n)
        node_cpu_fdata_out_d1 <= 32'b0;
    else if(node_cpu_rden_d1)
        node_cpu_fdata_out_d1 <= node_cpu_fdata_out;
    else
        node_cpu_fdata_out_d1 <= node_cpu_fdata_out_d1;
end
always@(posedge clk or negedge rst_n)begin
    if(~rst_n)
        classflow_cpu_fdata_out_d1 <= 32'b0;
    else if(classflow_cpu_rden_d1)
        classflow_cpu_fdata_out_d1 <= classflow_cpu_fdata_out;
    else
        classflow_cpu_fdata_out_d1 <= classflow_cpu_fdata_out_d1;
end

always@(posedge clk or negedge rst_n)begin
    if(~rst_n)
        np_data_out <= 32'b0;
    else if(node_cpu_rden_d2)
        np_data_out <= node_cpu_fdata_out_d1;
    else if(classflow_cpu_rden_d2)
        np_data_out <= classflow_cpu_fdata_out_d1;
    // else if(reg_rden_in_d1&&(reg_addr_in_d1==`ADDR_RAM_DP_CFG_REGISTER))
    //     np_data_out <= {20'b0,ram_dp_cfg_register};
    else
        np_data_out <= np_data_out;
end

always@(posedge clk or negedge rst_n)begin
    if(~rst_n)
        np_rd_vld <= 1'b0;
    else if(node_cpu_rden_d2 || classflow_cpu_rden_d2)
        np_rd_vld <= 1'b1;
    else
        np_rd_vld <= 1'b0;
end


endmodule

